﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.HomeServer.Controls;
using TV4Home.Server.IssueReporting;

namespace Microsoft.HomeServer.HomeServerConsoleTab.TV4Home.Server.WHS.AddIn
{
    public partial class BugReportFormControl : UserControl
    {
        private BugReportSubmittingForm submitProgress;

        public BugReportFormControl()
        {
            InitializeComponent();

            this.tpDescription.BackColor = CommonSettings.WizardBackColor;
            this.tpAttachments.BackColor = CommonSettings.WizardBackColor;

            this.lstAttachments.Columns[0].Width = 435;

            // prepopulate description field with general information
            txtDescription.Text = String.Format("{0}{0}{0}{0}{0}----- General information ----- {0}Add-In Version: {1}{0}Server Version: {2}{0}MediaPortal TV Server Version: {3}",
                                                Environment.NewLine,
                                                Utils.Misc.AddInVersion,
                                                FileVersionInfo.GetVersionInfo(Application.StartupPath + "\\HomeServerConsole.exe").ProductVersion,
                                                File.Exists(Utils.CommonPaths.TVServer_SetupTvEXEPath) ? FileVersionInfo.GetVersionInfo(Utils.CommonPaths.TVServer_SetupTvEXEPath).FileVersion : "(not installed)");

            // set cursor to title field
            this.txtTitle.Select();
        }

        public bool Commit()
        {
            // create issue object
            WebIssue issue = new WebIssue
            {
                Title = String.Format("[{0}] {1}", rbIssue.Checked ? "BUG" : "FRQ", txtTitle.Text),
                Description = txtDescription.Text,
                WorkItemType = rbIssue.Checked ? "Issue" : "Feature",
                Component = @"TV4Home\WHS Add-In",
                Priority = new[] { "Low", "Medium", "High" }[rbPriorityLow.Checked ? 0 : (rbPriorityMedium.Checked ? 1 : (rbPriorityHigh.Checked ? 2 : 0))]
            };

            // add attachments
            foreach (ListViewItem item in this.lstAttachments.Items)
            {
                if (item.Tag is WebAttachment)
                    issue.AddAttachment((WebAttachment)item.Tag);
            }

            submitProgress = new BugReportSubmittingForm();

            bgwSubmit.RunWorkerAsync(issue);

            // show progress form
            DialogResult result = submitProgress.ShowDialog();

            return result == DialogResult.OK;
        }

        private void bgwSubmit_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // operation succeeded
            if (e.Error == null)
            {
                using (BugReportSubmitSuccessForm successForm = new BugReportSubmitSuccessForm(e.Result as string))
                    successForm.ShowDialog();

                this.submitProgress.DialogResult = DialogResult.OK;
                this.submitProgress.Close();

                return;
            }

            // an error occurred
            if (e.Error is ArgumentException)
            {
                QMessageBox.Show("Please provide additional data",
                                 e.Error.Message,
                                 "Information",
                                 MessageBoxButtons.OK,
                                 MessageBoxIcon.Warning);
            }
            else
            {
                QMessageBox.Show("An error occurred while submitting the bug report",
                                 e.Error.Message,
                                 "Error",
                                 MessageBoxButtons.OK,
                                 MessageBoxIcon.Error);
            }

            this.submitProgress.DialogResult = DialogResult.Cancel;
            this.submitProgress.Close();
        }

        private void bgwSubmit_DoWork(object sender, DoWorkEventArgs e)
        {
            WebIssue issue = (WebIssue)e.Argument;

            // input validation
            if (String.IsNullOrEmpty(issue.Title) || issue.Title.Length < 9 || issue.Title.Length > 80)
                throw new ArgumentException("Title must be at least 3 characters long and mustn't exceed 80 characters!"); //TODO: localize exception

            if (String.IsNullOrEmpty(issue.Description) || issue.Description.Length < 10 || issue.Description.Length > 1500)
                throw new ArgumentException("Please enter between 10 and 1500 characters for the description!"); //TODO: localize exception

            // submit report
            e.Result = SubmitBugReport(issue);
        }

        private string SubmitBugReport(WebIssue issue)
        {
            // report the issue
            new IssueReporting().UploadIssue(issue);

            return issue.IssueId.ToString();
        }

        private void btnBrowseAttachment_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK != ofdAttachment.ShowDialog())
                return;

            this.txtAttachmentFilePath.Text = this.ofdAttachment.FileName;
        }

        private void btnAddAttachment_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(this.txtAttachmentFilePath.Text))
                return;

            FileInfo fInfo = new FileInfo(this.txtAttachmentFilePath.Text);

            if (!fInfo.Exists)
                return;

            // validate file size
            if (fInfo.Length > 350000)
            {
                QMessageBox.Show("Attachment is too large!",
                                 "Please use an attachment smaller than 350kB or compress the attachment.",
                                 "Information",
                                 MessageBoxButtons.OK,
                                 MessageBoxIcon.Information);

                return;
            }

            ListViewItem item = new ListViewItem(fInfo.Name);

            item.Tag = new WebAttachment()
            {
                AttachmentFilename = fInfo.Name,
                AttachmentData = Convert.ToBase64String(File.ReadAllBytes(fInfo.FullName)),
                AttachmentComment = txtAttachmentDescription.Text
            };

            this.lstAttachments.Items.Add(item);

            // clear fields
            this.txtAttachmentFilePath.Clear();
            this.txtAttachmentDescription.Clear();
        }

        private void btnRemoveAttachment_Click(object sender, EventArgs e)
        {
            if (this.lstAttachments.SelectedItems.Count > 0)
                this.lstAttachments.Items.Remove(this.lstAttachments.SelectedItems[0]);
        }
    }

    public class BugReportForm : Wizard
    {
        public BugReportForm()
        {
            base.Width = Microsoft.HomeServer.Controls.CommonSettings.PropertyPageStdWidth;
            base.Height = Microsoft.HomeServer.Controls.CommonSettings.PropertyPageStdHeight;
            base.WizardIcon = Icon.FromHandle(((Bitmap)Microsoft.HomeServer.Controls.CommonSettings.InformationImage24x24).GetHicon());
            base.Text = "Report a bug";

            base.Init();

            base.SetTypes(new Type[] { typeof(WP_BugReportForm) });
        }
    }

    public class WP_BugReportForm : WizardPage
    {
        private BugReportFormControl control;

        public WP_BugReportForm(Wizard parentWizard, object currentSubject, object currentParameter)
        {
            base.ParentWizard = parentWizard;

            base.OkButtonName = CommonSettings.WizardStandardButtonNameOk;
            base.CancelButtonName = CommonSettings.WizardStandardButtonNameCancel;

            base.Init();

            base.HideTopBannerAndLines = true;
            base.BackColor = CommonSettings.PropertyPageStdBackColor;

            base.OkButtonEnabled = true;
            base.CancelButtonEnabled = true;

            base.OkButton.DialogResult = DialogResult.OK;
            base.CancelButton.DialogResult = DialogResult.Cancel;

            base.OkButtonhook(OkButton_Clicked);
            base.CancelButtonhook(CancelButton_Clicked);

            base.ParentWizard.AcceptButton = null;
            base.ParentWizard.CancelButton = base.CancelButton;

            control = new BugReportFormControl();
            base.PlaceControlIntoWizardPage(control);
        }

        private void OkButton_Clicked(object sender, EventArgs e)
        {
            bool close = control.Commit();

            base.ParentWizard.PreventClose = !close;
        }

        private void CancelButton_Clicked(object sender, EventArgs e)
        {
            base.ParentWizard.PreventClose = false;
        }
    }
}